﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BotDetector.Core.Model;
using System.Configuration;
using System.Net.Http;
using System.Net.Http.Headers;
using BotDetector.Core.Converter;
using Newtonsoft.Json;
using System.Runtime.Serialization.Json;
using BotDetector.Core.Detector;

namespace BotDetector.Core.Search
{
    public class GoogleSearch : ISearch
    {
        private const string ClosedBracket = "]";
        private const string EmptyString = "";

        private BotDetectorConfigurator BotDetectorConfigurator = new BotDetectorConfigurator();
        private GoogleSearchConfigurator GoogleSearchConfigurator = new GoogleSearchConfigurator();

        private StringBuilder UrlParameters = new StringBuilder();
        private IConverter<object, ResultItemList> converter = new ConvertFromDynamicToResultItemList();

        public GoogleSearch()
        {

            UrlParameters.Append(BotDetectorConfigurator.apiKeyGoogle)
                .Append(BotDetectorConfigurator.customSearchEngineGoogle)
                .Append(BotDetectorConfigurator.doNotApplyFilteringGoogle);
        }

        public ResultItemList Search(string phrase)
        {            
            ResultItemList resultList = new ResultItemList();
            resultList.Phrase = phrase;
            int indexOfFirstResultReturned = 1;
            int numberOfMaxResults = 51;

            while (indexOfFirstResultReturned < numberOfMaxResults)
            {
                AddUrlParameters(phrase, indexOfFirstResultReturned);
                HttpResponseMessage response = SendRequestToServer(UrlParameters.ToString());
                dynamic json = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
                resultList = AddCurrentResultsToResultsList(resultList, json);
                indexOfFirstResultReturned += 10;
            }
            return resultList;
        }

        private ResultItemList AddCurrentResultsToResultsList(ResultItemList resultList, dynamic json)
        {
            ResultItemList results = converter.Convert(json);
            foreach (ResultItem result in results)
            {
                resultList.Add(result);
            }
            return resultList;
        }

        private void AddUrlParameters(string phrase, int indexOfFirstResultReturned)
        {
            const string questionQueryParameter = "&q=";
            const string indexOfFirstResultReturnedParameter = "&start=";

            UrlParameters.Append(questionQueryParameter)
                         .Append(phrase)
                         .Append(indexOfFirstResultReturnedParameter)
                         .Append(indexOfFirstResultReturned);
        }

        private HttpResponseMessage SendRequestToServer(string urlParameters)
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(BotDetectorConfigurator.urlGoogle);

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = client.GetAsync(urlParameters).Result;
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException("Error message is " + response.StatusCode.ToString());
            }

            return response;
        }

        public void ConfigureSearch(string language = EmptyString,
                            string country = EmptyString,
                            int pastDays = 0,
                            int pastWeeks = 0,
                            int pastMonths = 0,
                            int pastYears = 0)
        {
            if (!language.Equals(string.Empty))
            {
                RestrictSearchToLanguage(language);
            }

            if (!country.Equals(string.Empty))
            {
                RestrictSearchToCountry(country);
            }

            if (pastDays != 0)
            {
                RestrictSearchToPastDays(pastDays);
            }

            if (pastWeeks != 0)
            {
                RestrictSearchToPastWeeks(pastWeeks);
            }

            if (pastMonths != 0)
            {
                RestrictSearchToPastMonths(pastMonths);
            }

            if (pastYears != 0)
            {
                RestrictSearchToPastYears(pastYears);
            }
        }


        private void RestrictSearchToLanguage(string language)
        {
            const string languageQueryParameter = "&lr=";

            UrlParameters.Append(languageQueryParameter)
                .Append(GoogleSearchConfigurator.Languages[language]);
        }

        private void RestrictSearchToCountry(string country)
        {
            const string countryQueryParameter = "&cr=";

            UrlParameters.Append(countryQueryParameter)
                .Append(GoogleSearchConfigurator.Countries[country]);
        }

        private void RestrictSearchToPastDays(int numberOfDays)
        {
            const string dateQueryParameter = "&dateRestrict=d[";

            UrlParameters.Append(dateQueryParameter)
                .Append(numberOfDays)
                .Append(ClosedBracket);
        }

        private void RestrictSearchToPastWeeks(int numberOfWeeks)
        {
            const string dateQueryParameter = "&dateRestrict=w[";

            UrlParameters.Append(dateQueryParameter)
                .Append(numberOfWeeks)
                .Append(ClosedBracket);
        }

        private void RestrictSearchToPastMonths(int numberOfMonths)
        {
            const string dateQueryParameter = "&dateRestrict=m[";

            UrlParameters.Append(dateQueryParameter)
                .Append(numberOfMonths)
                .Append(ClosedBracket);
        }

        private void RestrictSearchToPastYears(int numberOfYears)
        {
            const string dateQueryParameter = "&dateRestrict=y[";

            UrlParameters.Append(dateQueryParameter)
                .Append(numberOfYears)
                .Append(ClosedBracket);
        }





    }
}
